package com.qianyu.core.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qianyu.core.entity.base.BaseIdDto;
import com.qianyu.core.entity.bean.*;
import com.qianyu.core.entity.dto.QqRentOrderDto;
import com.qianyu.core.entity.vo.QqRentOrderVo;
import com.qianyu.core.enumerate.DataStatusEnum;
import com.qianyu.core.enumerate.ResultEnum;
import com.qianyu.core.exception.CustomerException;
import com.qianyu.core.helper.LoginHelper;
import com.qianyu.core.mapper.QqRentOrderMapper;
import com.qianyu.core.service.*;
import com.qianyu.core.util.TimeUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

@Service
@RequiredArgsConstructor
public class QqRentOrderServiceImpl extends ServiceImpl<QqRentOrderMapper, QqRentOrder> implements QqRentOrderService {

    private final QqOrderItemService qqOrderItemService;

    private final QqAccountService qqAccountService;

    private final UserService userService;

    private final MoneyWaterService moneyWaterService;

    @Override
    public BigDecimal getAmount(QqRentOrderDto.RentDto dto) {
        User user = LoginHelper.getLoginUser();
        BigDecimal rent = user.getDayRent();
        return rent.multiply(BigDecimal.valueOf(dto.getDay())).multiply(BigDecimal.valueOf(dto.getAccountNum()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addOrder(QqRentOrderDto.RentDto dto) {

        List<QqAccount> accounts = qqAccountService.listAccountIsAble(dto.getAccountNum());
        if (CollectionUtils.isEmpty(accounts)) {
            throw new CustomerException(ResultEnum.NO_QQ_ACCOUNT_ABLE);
        }
        User user = LoginHelper.getLoginUser();
        if (user.getRole() != 1) {
            throw new CustomerException(ResultEnum.USER_ID_IS_ABNORMAL);
        }
        BigDecimal amount = getAmount(dto);
        if (user.getMoney().compareTo(amount) < 0) {
            throw new CustomerException(ResultEnum.USER_MONET_NOT_ENOUGH);
        }
        QqRentOrder order = new QqRentOrder();
        order.setAgencyId(user.getId());
        order.setOrderPrice(amount);
        order.setNum(dto.getAccountNum());
        order.setDayNum(dto.getDay());
        order.setSn("ZHPT" + TimeUtil.unixTime());
        order.setPrice(user.getDayRent());
        order.setDeleteStatus(DataStatusEnum.ISABLE.getVal());
        order.setCompleteTime(new Date());
        order.setRealNum(accounts.size());
        order.setStatus(2);
        //保存租用订单
        save(order);
        List<QqOrderItem> items = new ArrayList<>();

        for (QqAccount account : accounts) {
            QqOrderItem item = new QqOrderItem();
            item.setStatus(1);
            item.setOrderId(order.getId());
            item.setNum(dto.getDay());
            item.setQid(account.getId());
            item.setPayPrice(amount);
            item.setRentExpire(TimeUtil.toExpireDate(dto.getDay()));
            item.setOriginQnum(account.getQnum());
            items.add(item);

            //修改账号状态
            LambdaUpdateWrapper<QqAccount> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.set(QqAccount::getAgencyId, user.getId()).set(QqAccount::getRentStatus, 1)
                    .set(QqAccount::getRentTime, TimeUtil.unixTime()).set(QqAccount::getStatusChangeTime, TimeUtil.unixTime())
                    .set(QqAccount::getRentExpire, TimeUtil.unixTime(TimeUtil.toExpireDate(dto.getDay())))
                    .set(QqAccount::getDispatchTime, TimeUtil.unixTime()).eq(QqAccount::getId, account.getId());
            qqAccountService.update(updateWrapper);
        }

        //添加订单账号
        qqOrderItemService.saveBatch(items);
        //更新用户金额
        user.setMoney(user.getMoney().subtract(amount));
        userService.updateById(user);
        //新增钱包流水
        MoneyWater moneyWater = new MoneyWater() {{
            setUserId(user.getId());
            setBalance(amount);
            setAfterBalance(user.getMoney());
            setRemark("租号");
            setType(2);
            setIsIncome(2);
        }};
        moneyWaterService.save(moneyWater);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean continueOrderAccount(QqRentOrderDto.RentContinueDto dto) {

        List<QqAccount> accounts = qqAccountService.listAccountIsAble(dto.getAccountNum());

        if (CollectionUtils.isEmpty(accounts)) {
            throw new CustomerException(ResultEnum.NO_QQ_ACCOUNT_ABLE);
        }

        List<QqOrderItem> orderItems = qqOrderItemService.list(Wrappers.<QqOrderItem>lambdaQuery().in(QqOrderItem::getOrderId, dto.getOrderIds()));

        List<Long> accountIds = new ArrayList<>();

        User user = LoginHelper.getLoginUser();
        BigDecimal amount = getAmount(dto);
        Collection<QqRentOrder> orders = listByIds(dto.getOrderIds());
        for (QqRentOrder order : orders) {
            order.setOrderPrice(order.getOrderPrice().add(amount));
            order.setNum(order.getNum() + dto.getAccountNum());
            order.setDayNum(order.getDayNum() + dto.getDay());
            order.setCompleteTime(new Date());
            order.setType(1);
            order.setRealNum(order.getRealNum() + accounts.size());
        }
        //修改订单状态
        updateBatchById(orders);

        //处理订单账号
        for (QqOrderItem item : orderItems) {
            item.setType(1);
            item.setNum(item.getNum() + dto.getDay());
            item.setPayPrice(item.getPayPrice().add(amount));
            item.setRentExpire(TimeUtil.toExpireDate(dto.getDay()));
            accountIds.add(item.getQid());
        }
        //更新订单账号
        qqOrderItemService.updateBatchById(orderItems);

        //更新qq账号租用到期时间
        qqAccountService.update(Wrappers.<QqAccount>lambdaUpdate()
                .set(QqAccount::getRentExpire, TimeUtil.unixTime(TimeUtil.toExpireDate(dto.getDay())))
                .set(QqAccount::getRentStatus, 1).in(QqAccount::getId, accountIds));

        //更新用户金额
        user.setMoney(user.getMoney().subtract(amount));
        userService.updateById(user);
        //新增钱包流水
        MoneyWater moneyWater = new MoneyWater() {{
            setUserId(user.getId());
            setBalance(amount);
            setAfterBalance(user.getMoney());
            setRemark("续期");
            setType(2);
            setIsIncome(2);
        }};
        moneyWaterService.save(moneyWater);
        return true;
    }

    @Override
    public Page<QqRentOrderVo.RentOrderPage> pageList(QqRentOrderDto.RentOrderPageDto dto) {
        Page<QqRentOrder> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        Page<QqRentOrderVo.RentOrderPage> orderPage = new Page<>();
        LambdaQueryWrapper<QqRentOrder> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(!ObjectUtils.isEmpty(dto.getStatus()), QqRentOrder::getStatus, dto.getStatus())
                .eq(!ObjectUtils.isEmpty(dto.getType()), QqRentOrder::getType, dto.getType())
                .ge(!ObjectUtils.isEmpty(dto.getStartTime()), QqRentOrder::getCreateTime, dto.getStartTime())
                .le(!ObjectUtils.isEmpty(dto.getEndTime()), QqRentOrder::getCreateTime, TimeUtil.toDayLastTime(dto.getEndTime()))
                .eq(QqRentOrder::getAgencyId, LoginHelper.getUserId());
        IPage<QqRentOrder> orderIPage = baseMapper.selectPage(page, wrapper);
        BeanUtil.copyProperties(orderIPage, orderPage);
        return orderPage;
    }

    @Override
    public QqRentOrderVo.RentOrderInfo getInfo(BaseIdDto dto) {
        QqRentOrderVo.RentOrderInfo info = BeanUtil.copyProperties(baseMapper.selectById(dto.getId()), QqRentOrderVo.RentOrderInfo.class);
        info.setItems(qqOrderItemService.list(Wrappers.<QqOrderItem>lambdaQuery().eq(QqOrderItem::getOrderId, dto.getId())));
        return info;
    }
}
